package com.sunwayhorizo.health.business.clinic.emr.document;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.clinic.emr.document.query.DocumentQueryLocal;
import com.sunwayhorizo.health.business.clinic.emr.observation.ObservationManagerLocal;
import com.sunwayhorizo.health.business.clinic.emr.template.query.TemplateQueryLocal;
import com.sunwayhorizo.health.business.dto.clinic.emr.document.EmrWriterDTO;
import com.sunwayhorizo.health.business.dto.patad.empi.PatientBaseInfoDTO;
import com.sunwayhorizo.health.business.registries.employee.EmployeeManagerLocal;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.DateUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.CE;
import com.sunwayhorizo.health.hl7.datatypes.CS;
import com.sunwayhorizo.health.hl7.datatypes.ED;
import com.sunwayhorizo.health.hl7.datatypes.ST;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.Document;
import com.sunwayhorizo.health.hl7.rim.Observation;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.ActMood;
import com.sunwayhorizo.health.hl7.vocabulary.ActRelationshipType;
import com.sunwayhorizo.health.hl7.vocabulary.ActStatus;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;

/**
 * @ClassName DocumentCommonManager <br>
 * @PackageName com.sunwayhorizo.health.business.clinic.emr.document <br>
 * @Description 电子病历书写公共部分 <br>
 * @Author jinzw <br>
 * @Date 2011-03-10 <br>
 * @Version 1.0 <br>
 * @ModifiedDesc <br>
 * @ModifiedDate 2011-06-20<br>
 * @ModifiedBy jinzw<br>
 * @Copyright 2010-2020 北京三维海容 All Rights Reserved. <br>
 */
@Stateless
@Name(value = "DocumentCommonManager")
public class DocumentCommonManager extends BaseManager implements DocumentCommonManagerLocal
{

    private TemplateQueryLocal templateQuery = (TemplateQueryLocal) Component.getInstance("TemplateQuery");
    private DocumentQueryLocal documentQuery = (DocumentQueryLocal) Component.getInstance("DocumentQuery");
    
    public Document creatClinicalDocument(String code) throws Hl7Exception
    {
        if (StrUtil.isEmpty(code))
        {
            return null;
        }
        CS cs = ActMood.EVN;
        // code值
        CE ce = DataTypeUtil.getCE(code); 
        Document document = this.getActFactory().newClinicalDocument(cs, ce, null);
        document.setStatusCode(ActStatus.ACTIVE);
        return document;
    }


    @SuppressWarnings("rawtypes")
    public String delDoc(List ids) throws Hl7Exception
    {
        try
        {
            String id = (String) ids.get(0);
            Document doc = baseQuery.findDocumentById(id);
            em.remove(doc);
        }
        catch (Exception e)
        {
            return "-1";
        }
        return "1";
    }


    public Document findDoc(String emrClassRoleId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(emrClassRoleId))
        {
            log.info("查询电子病历失败，没有找到emrClassRoleId");
            return null;
        }
        List<Object> objs = documentQuery.findActIdByTempClassRoleId(emrClassRoleId);
        if (ListUtil.isEmpty(objs))
        {
            log.info("查询电子病历失败，没有找到actId");
            return null;
        }
        String actId = objs.get(0).toString();
        Document doc = baseQuery.findDocumentById(actId);
        return doc;
    }


    /**
     * 该方法用在病历书写的修改中
     */
    public void setParticipation(EmrWriterDTO emr, Document doc) throws Hl7Exception
    {
        //患者角色
        Role patientRole = null;
        if (StrUtil.isNotBlank(emr.getPatientRoleId()))
        {
            patientRole = baseQuery.findRoleById(Long.parseLong(emr.getPatientRoleId()));
        }
        //电子病历书写分类角色
        Role classRole = null; 
        if (StrUtil.isNotBlank(emr.getRimRoleEmrWriterClassId()))
        {
            classRole = templateQuery.findClassRoleByEntId(emr.getRimRoleEmrWriterClassId());
        }

        // 设置三级医生签名
        if (StrUtil.isNotEmpty(emr.getEmpRoleId()))
        {
            threeLevelInfo(emr, doc); 
        }

        if (null != patientRole)
        {
            ActParticipation participation = new ActParticipation();
            if (StrUtil.isNotEmpty(emr.getMacroContents()))
            {
                // 患者入院记录中单独保存的json字符串
                ED ed = DataTypeUtil.getED(emr.getMacroContents());
                participation.setNoteText(ed);
            }
            participation.setTypeCode(ParticipationType.RCT);
            doc.addParticipation(participation, patientRole); // 患者关联信息
        }
        if (null != classRole)
            doc.addPartWithOutEntRole(ParticipationType.HLD, classRole); // 病历分类
    }


    public Document injectDtoToDoc(EmrWriterDTO emr, Document document) throws Hl7Exception
    {

        // 设置病历名称
        if (!StrUtil.isEmpty(emr.getName()))
        {
            ST name = getDataTypeFactory().newST(emr.getName());
            document.setTitle(name);
        }

        // 文书分类监控代码
        if (StrUtil.isNotEmpty(emr.getTemplateCode()))
        {
            CE templateCode = getDataTypeFactory().newCE(emr.getTemplateCode());
            document.setLevelCode(templateCode);
        }

        // 病历内容
        byte[] contents = emr.getContents();
        if (null != contents)
        { // 如果内容不为空
            ED desc = DataTypeUtil.getED("", contents);
            document.setText(desc);
        }

        // 病历状态 0 实习医生书写 1 书写 2 住院医生签字 3 上级医生签名 4 主任医生签名
        if (StrUtil.isNotEmpty(emr.getSignature()))
        {
            ST medRecordsState = DataTypeUtil.getST(emr.getSignature());
            document.setMedRecordsState(medRecordsState);
        }

        // 病程标题时间
        if (StrUtil.isNotEmpty(emr.getMedProDate()))
        {
            document.setStorageCode(DataTypeUtil.getCE(emr.getMedProDate()));
        }

        // 创建人
        if (!StrUtil.isEmpty(emr.getCreatedBy()))
        {
            document.setCreatedBy(Long.parseLong(emr.getCreatedBy()));
            document.setCreationDate(DateUtil.getTimestamp(DateUtil.GetDateTime()));
        }

        // 最后修改人
        if (!StrUtil.isEmpty(emr.getLastUpdateBy()))
        {
            document.setLastUpdatedBy(Long.parseLong(emr.getLastUpdateBy()));
            document.setLastUpdateDate(DateUtil.getTimestamp(DateUtil.GetDateTime()));
        }
        
        //会诊单号
        if(StrUtil.isNotEmpty(emr.getConsultationId()))
        {
            document.setCompletionCode(DataTypeUtil.getCE(emr.getConsultationId()));
        }

        return document;
    }


    public Document injectDtoToDocNotFile(EmrWriterDTO emr, Document document) throws Hl7Exception
    {
        // 设置病历名称
        if (!StrUtil.isEmpty(emr.getName()))
        {
            ST name = getDataTypeFactory().newST(emr.getName());
            document.setTitle(name);
        }
        // 模板分类监控代码
        if (StrUtil.isNotEmpty(emr.getTemplateCode()))
        {
            CE templateCode = getDataTypeFactory().newCE(emr.getTemplateCode());
            document.setLevelCode(templateCode);
        }

        // 病历状态 0 实习医生书写 1 书写 2 住院医生签字 3 上级医生签名 4 主任医生签名
        if (StrUtil.isNotEmpty(emr.getSignature()))
        {
            ST medRecordsState = DataTypeUtil.getST(emr.getSignature());
            document.setMedRecordsState(medRecordsState);
        }
        // 病程标题时间
        if (StrUtil.isNotEmpty(emr.getMedProDate()))
        {
//             document.setAvailabilityTime(DataTypeUtil.getTS(DateUtil.getFormatString(emr.getMedProDate())));
            document.setStorageCode(DataTypeUtil.getCE(emr.getMedProDate()));
        }

        // 创建人
        if (!StrUtil.isEmpty(emr.getCreatedBy()))
        {
            document.setCreatedBy(Long.parseLong(emr.getCreatedBy()));
            document.setCreationDate(DateUtil.getTimestamp(DateUtil.GetDateTime()));
        }

        // 最后修改人
        if (!StrUtil.isEmpty(emr.getLastUpdateBy()))
        {
            document.setLastUpdatedBy(Long.parseLong(emr.getLastUpdateBy()));
            document.setLastUpdateDate(DateUtil.getTimestamp(DateUtil.GetDateTime()));
        }
        //会诊单号
        if(StrUtil.isNotEmpty(emr.getConsultationId()))
        {
            document.setCompletionCode(DataTypeUtil.getCE(emr.getConsultationId()));
        }

        return document;
    }


    public EmrWriterDTO convertDocToDto(Document doc) throws Hl7Exception
    {
        if (null == doc)  return null;
        EmrWriterDTO ewd = new EmrWriterDTO();
        // id
        if (null != doc.getActId())
        {
            ewd.setId(doc.getActId().toString());
        }

        // 名称
        if (null != doc.getTitle())
        {
            ST name = doc.getTitle();
            ewd.setName(name.stringValue());
        }
        // 分类监控代码
        if (null != doc.getCode())
        {
            ewd.setClassCode(doc.getCode().code().toString());
        }
        // 模板监控代码（在病历书写中主要是病历分类监控代码）
        if (null != doc.getLevelCode())
        {
            ewd.setTemplateCode(doc.getLevelCode().code().toString());
        }
        // 病历书写状态
        if (null != doc.getMedRecordState())
        {
            ST negationInd = doc.getMedRecordState();
            ewd.setSignature(negationInd.toString());
        }

        // 内容
        if (null != doc.getText())
        {
            ED text = doc.getText();
            ewd.setContents(text.integrityCheck().byteArray());
        }

        // //病程标题时间
        // if(null != doc.getAvailabilityTime().toString())
        // {
        // ewd.setMedProDate(DateUtil.formatStr(doc.getAvailabilityTime().toString()));
        // }

        // 创建人
        if (null != doc.getCreatedBy().toString())
        {
            ewd.setCreatedBy(doc.getCreatedBy().toString());
        }

        // 创建时间
        if (null != doc.getCreationDate())
        {
            ewd.setCreationDate(DateUtil.getFormatTimestamp(doc.getCreationDate(), "yyyy-mm-dd hh:mm:ss")); // 创建时间
        }

        // 最后修改人
        if (null != doc.getLastUpdatedBy())
        {
            ewd.setLastUpdateBy(doc.getLastUpdatedBy().toString());
        }

        // 最后修改时间
        if (null != doc.getLastUpdateDate())
        {
            ewd.setLastUpdateDate(DateUtil.getFormatTimestamp(doc.getLastUpdateDate(), "yyyy-mm-dd hh:mm:ss")); // 修改时间
        }
        //会诊单号
        if( doc.getCompletionCode() != null &&  doc.getCompletionCode().isNull().isFalse())
        {
            ewd.setConsultationId( doc.getCompletionCode().code().toString());
        }
       

        return ewd;
    }


    @SuppressWarnings("rawtypes")
    public List<EmrWriterDTO> convertDtoToList(List list) throws Hl7Exception
    {
        if (ListUtil.isEmpty(list)) return null;
        List<EmrWriterDTO> emrWriterList = new ArrayList<EmrWriterDTO>();
        EmployeeManagerLocal empManager = (EmployeeManagerLocal) Component.getInstance("EmployeeManager");
        if (ListUtil.isNotEmpty(list))
        {
            for (int i = 0; i < list.size(); i++)
            {
                Object[] arg = (Object[]) list.get(i);
                EmrWriterDTO emrWriter = new EmrWriterDTO();
                if (null != arg[0] && StrUtil.isNotEmpty(arg[0].toString()))
                {
                    emrWriter.setId(arg[0].toString());
                }
                if (null != arg[1] && StrUtil.isNotEmpty(arg[1].toString()))
                {
                    emrWriter.setName(arg[1].toString());
                }
                if (null != arg[2] && StrUtil.isNotEmpty(arg[2].toString()))
                {
                    emrWriter.setSignature(arg[2].toString());
                }
                if (null != arg[4] && StrUtil.isNotEmpty(arg[4].toString()))
                {
                    emrWriter.setClassCode(arg[4].toString());
                }
                if (null != arg[5] && StrUtil.isNotEmpty(arg[5].toString()))
                {
                    emrWriter.setCreatedBy(arg[5].toString());
                }

                PatientBaseInfoDTO patientBaseInfo1 = empManager.findPlayEntityByRoleId(Long.parseLong(arg[5].toString()));
                if (null != patientBaseInfo1)
                {
                    emrWriter.setCreateByName(patientBaseInfo1.getNatureName());
                }
                if (null != arg[6] && StrUtil.isNotEmpty(arg[6].toString()))
                {
                    String str = arg[6].toString().substring(0, 19);
                    emrWriter.setCreationDate(str);
                }
                if (null != arg[7] && StrUtil.isNotEmpty(arg[7].toString()))
                {
                    emrWriter.setTemplateCode(arg[7].toString());
                }
                if (null != arg[8] && StrUtil.isNotEmpty(arg[8].toString()))
                {
                    emrWriter.setMedProDate(arg[8].toString());
                }
                if (null != arg[9] && StrUtil.isNotEmpty(arg[9].toString()))
                {
                    emrWriter.setConsultationId(arg[9].toString());
                }
                setThreeLevelDtoToPrtcptns(Long.valueOf(arg[0].toString()), emrWriter);// 三级医生列表展示信息
                emrWriterList.add(emrWriter);
            }
        }
        return emrWriterList;
    }


    public void setThreeLevelDtoToPrtcptns(Long ActId, EmrWriterDTO emr) throws Hl7Exception
    {
        EmployeeManagerLocal empManager = (EmployeeManagerLocal) Component.getInstance("EmployeeManager");
        List<ActParticipation> prtcptnsList = baseQuery.findPrtcptnsByActId(ActId);
        if (ListUtil.isNotEmpty(prtcptnsList))
        {
            for (ActParticipation prtcptns : prtcptnsList)
            {
                // 住院医生
                if (prtcptns.getTypecode().equals(ParticipationType.ESC))
                {
                    Role empRole = (Role) prtcptns.getRoleparticipation();
                    PatientBaseInfoDTO patientBaseInfoDTO = empManager.findPlayEntityByRole(empRole);
                    emr.setEmpRoleId(patientBaseInfoDTO.getNatureName());
                    if (null != prtcptns.getCreateTime())
                    {
                        emr.setLowSignatureDate(prtcptns.getCreateTime().toDateString());
                    }
                }
                // 主治医生
                if (prtcptns.getTypecode().equals(ParticipationType.DIS))
                {
                    Role empRole = (Role) prtcptns.getRoleparticipation();
                    PatientBaseInfoDTO patientBaseInfoDTO = empManager.findPlayEntityByRole(empRole);
                    emr.setHigherSignature(patientBaseInfoDTO.getNatureName());
                    if (null != prtcptns.getCreateTime())
                    {
                        emr.setHigherSignatureDate(prtcptns.getCreateTime().toDateString());
                    }
                }
                // 主任医生
                if (prtcptns.getTypecode().equals(ParticipationType.CON))
                {
                    Role empRole = (Role) prtcptns.getRoleparticipation();
                    PatientBaseInfoDTO patientBaseInfoDTO = empManager.findPlayEntityByRole(empRole);
                    emr.setDirectorSignature(patientBaseInfoDTO.getNatureName());
                    if (null != prtcptns.getCreateTime())
                    {
                        emr.setDirectorSignatureDate(prtcptns.getCreateTime().toDateString());
                    }
                }
            }
        }
    }


    @Override
    public void setSignatureInfo(EmrWriterDTO emr, Document doc) throws Hl7Exception
    {
        threeLevelInfo(emr, doc);
        // 修改书写状态
        ST mdState = doc.getMedRecordState();
        if (!mdState.toString().equals(emr.getSignature()))
        {
            doc.setMedRecordsState(DataTypeUtil.getST(emr.getSignature()));
        }
    }


    /**
     * 设置三级医生信息
     * （次方法暂时保留，在修改结构化模板出来之后，该方法做相应调整）
     * @param emr
     * @param doc
     * @throws Hl7Exception
     */
    private void threeLevelInfo(EmrWriterDTO emr, Document doc) throws Hl7Exception
    {
        Role authorRole = null; // 医生签名角色
        ActParticipation participation = null;

        // 住院医师角色
        if (StrUtil.isNotEmpty(emr.getEmpRoleId()))
        {
            participation = new ActParticipation();
            participation.setTypeCode(ParticipationType.ESC);
            authorRole = baseQuery.findRoleById(Long.parseLong(emr.getEmpRoleId()));
        }
        // 上级医师角色
        if (StrUtil.isNotEmpty(emr.getHigherSignature()))
        {
            participation = new ActParticipation();
            authorRole = baseQuery.findRoleById(Long.parseLong(emr.getHigherSignature()));
            participation.setTypeCode(ParticipationType.DIS);
        }
        // 主任医师角色
        if (StrUtil.isNotEmpty(emr.getDirectorSignature()))
        {
            participation = new ActParticipation();
            authorRole = baseQuery.findRoleById(Long.parseLong(emr.getDirectorSignature()));
            participation.setTypeCode(ParticipationType.CON);
        }
        if (null != authorRole)
        {
            // participation.setStatCode(DataTypeUtil.getCS(BusinessConstants.AUT_ACTIVE));
            // //当前作者生效
            participation.setCreateTime(DataTypeUtil.getTS(DateUtil.getDate())); // 医生签名时间
            doc.addParticipation(participation, authorRole); // 医生签名关联关系
        }
        
    }

    /**
     * 设置病历书写中参与的Role
     * 
     * @param emr
     * @param doc
     * @throws Hl7Exception
     */
    public Map<CS,Role> findWriteEmrParticiRole(EmrWriterDTO emr) throws Hl7Exception
    {
        Map<CS,Role> scopeMap = new HashMap<CS,Role>();
        // 医生签名角色
        Role authorRole = null; 
        // 住院医师角色
        if (StrUtil.isNotEmpty(emr.getEmpRoleId()))
        {
            authorRole = baseQuery.findRoleById(Long.parseLong(emr.getEmpRoleId()));
            scopeMap.put(ParticipationType.ESC,authorRole);
        }
        // 上级医师角色
        if (StrUtil.isNotEmpty(emr.getHigherSignature()))
        {
            authorRole = baseQuery.findRoleById(Long.parseLong(emr.getHigherSignature()));
            scopeMap.put(ParticipationType.DIS,authorRole);
        }
        // 主任医师角色
        if (StrUtil.isNotEmpty(emr.getDirectorSignature()))
        {
            authorRole = baseQuery.findRoleById(Long.parseLong(emr.getDirectorSignature()));
            scopeMap.put(ParticipationType.CON,authorRole);
        }
        
        //患者角色
        Role patientRole = null;
        if (StrUtil.isNotEmpty(emr.getPatientRoleId()))
        {
            patientRole = baseQuery.findRoleById(Long.parseLong(emr.getPatientRoleId()));
            scopeMap.put(ParticipationType.RCT,patientRole);
        }
        //文书分类角色
        Role classRole = null; 
        if (StrUtil.isNotBlank(emr.getRimRoleEmrWriterClassId()))
        {
            classRole = templateQuery.findClassRoleByEntId(emr.getRimRoleEmrWriterClassId());
            scopeMap.put(ParticipationType.HLD,classRole);
        }
        
        return scopeMap;
    }
    
   
    
    //该方法为设置病历书写相关的诊断信息，应用在病历修改或者签名的时候增加诊断
    //后期如果有修改结构化模型，做相应的调整
    public void setRelationship(Document doc, EmrWriterDTO emr) throws Hl7Exception
    {
        List<Observation> list = documentQuery.findDiagnosisByPatientId(emr.getPatientRoleId(),emr.getPatientNum());
        // 删除该患者原有的诊断
        if (ListUtil.isNotEmpty(list))
        {
            for (int i = 0; i < list.size(); i++)
            {
                Observation act = (Observation) list.get(i);
                em.remove(act);
                em.flush();
            }
            //上次诊断已经从数据库中删除，clear缓存
            em.clear();
        }

        ObservationManagerLocal observationManager = (ObservationManagerLocal) Component.getInstance("ObservationManager");
        List<Observation> observationList = observationManager.newObservation(emr.getEmrDiagnosisList());
        if (ListUtil.isNotEmpty(observationList))
        {
            for (int i = 0; i < observationList.size(); i++)
            {
                Observation observation = observationList.get(i);
                // 诊断动作跟书写动作添加DIAG关系
                doc.addOBActRelWhithOutControlAct(ActRelationshipType.DIAG, observation);
            }
        }
    }
    
    public List<Observation> findObservationList(EmrWriterDTO emr) throws Hl7Exception
    {
        List<Observation> list = documentQuery.findDiagnosisByPatientId(emr.getPatientRoleId(),emr.getPatientNum());
        // 删除该患者原有的诊断
        if (ListUtil.isNotEmpty(list))
        {
            for (int i = 0; i < list.size(); i++)
            {
                Observation act = (Observation) list.get(i);
                em.remove(act);
                em.flush();
            }
        }
        ObservationManagerLocal observationManager = (ObservationManagerLocal) Component.getInstance("ObservationManager");
        List<Observation> observationList = observationManager.newObservation(emr.getEmrDiagnosisList());
        return observationList;

    }
    
    public void modifyMacro(Document doc,String macroContents) throws Hl7Exception
    {
     // 参与病历文件的所有角色
        List<ActParticipation> parts = doc.getParticipations();
        if (ListUtil.isNotEmpty(parts))
        {
            for (int i = 0; i < parts.size(); i++)
            {
                ActParticipation part = (ActParticipation) parts.get(i);
                // 找到患者参与的RimCoreActPrtcptns，把json格式的串设置给他
                if (part.getTypecode().equals(ParticipationType.RCT))
                {
                    if (StrUtil.isNotEmpty(macroContents))
                    {
                        // 宏员素json字符串
                        ED ed = DataTypeUtil.getED(macroContents);
                        part.setNoteText(ed);
                    }
                    em.merge(part);
                }
            }
        }
    }

}
